
package com.chongchong.user.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chongchong.user.entity.User;
import com.chongchong.user.excel.UserExcel;
import com.chongchong.user.excel.UserImportListener;
import com.chongchong.user.service.IUserService;
import com.chongchong.user.vo.UserSuperVo;
import com.chongchong.user.vo.UserVO;
import com.chongchong.user.wrapper.UserWrapper;
import com.chongchong.core.log.exception.ServiceException;
import com.chongchong.core.tool.utils.ObjectUtil;

import com.chongchong.system.entity.Role;
import com.chongchong.system.service.IDeptService;
import com.chongchong.system.service.IRoleService;
import com.chongchong.system.vo.DeptVO;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.codec.Charsets;
import com.chongchong.core.mp.support.Condition;
import com.chongchong.core.mp.support.Query;
import com.chongchong.core.secure.SysUser;
import com.chongchong.core.secure.utils.SecureUtil;
import com.chongchong.core.tool.api.R;
import com.chongchong.core.tool.constant.SysConstant;
import com.chongchong.core.tool.utils.Func;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * 控制器
 *
 * @author
 */
@RestController
@RequestMapping("/user")
@AllArgsConstructor
@Api(tags = "用户相关")
public class UserController {

	private IUserService userService;

	private IDeptService deptService;

	/**
	 * 查询单条
	 */
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "查看详情", notes = "传入id")
	@GetMapping("/detail")
	public R<UserVO> detail(User user) {
		User detail = userService.getOne(Condition.getQueryWrapper(user));
		return R.data(UserWrapper.build().entityVO(detail));
	}

	/**
	 * 查询单条
	 */
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "查看详情", notes = "传入id")
	@GetMapping("/info")
	public R<UserVO> info(SysUser user) {
		User detail = userService.getById(user.getUserId());
		return R.data(UserWrapper.build().entityVO(detail));
	}

	/**
	 * 用户列表
	 */
	@GetMapping("/list")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "account", value = "账号名", paramType = "query", dataType = "string"),
		@ApiImplicitParam(name = "realName", value = "姓名", paramType = "query", dataType = "string")
	})
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "列表", notes = "传入account和realName")
	public R<IPage<UserVO>> list(@ApiIgnore @RequestParam Map<String, Object> user, Query query, SysUser sysUser) {
		QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
		IPage<User> pages = userService.page(Condition.getPage(query), (!sysUser.getTenantId().equals(SysConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(User::getTenantId, sysUser.getTenantId()) : queryWrapper);
		return R.data(UserWrapper.build().pageVO(pages));
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增或修改", notes = "传入User")
	public R submit(@Valid @RequestBody User user) {
		//因账号不能同时拥有外部与内部角色，并且当账号角色选择外部角色时为单选，所以需要做相应判断
		if (verifyRole(user)) {
			return R.fail(500, "账号不能同时拥有外部与内部角色并且当账号角色选择外部角色时为单选,请重新选择角色");
		}

		//上级主管不能是自己，需判断
		Long id = user.getId();
		if(id != null && id.equals(user.getParentId())){
			throw new ServiceException("上级主管不能为自己");
		}
		return R.status(userService.submit(user));
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入User")
	public R update(@Valid @RequestBody User user) {
		//因账号不能同时拥有外部与内部角色，并且当账号角色选择外部角色时为单选，所以需要做相应判断
		if (verifyRole(user)) {
			return R.fail(500, "账号不能同时拥有外部与内部角色并且当账号角色选择外部角色时为单选,请重新选择角色");
		}
		Date date = new Date();
		user.setUpdateTime(date);
		user.setUpdateUserId(SecureUtil.getUserId());
		//上级主管不能是自己，需判断
		Long id = user.getId();
		if(id != null && id.equals(user.getParentId())){
			throw new ServiceException("上级主管不能为自己");
		}
		return R.status(userService.updateById(user));
	}
	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "删除", notes = "传入地基和")
	public R remove(@RequestParam String ids) {
		return R.status(userService.removeByIds(Func.toLongList(ids)));
	}


	/**
	 * 设置菜单权限
	 *
	 * @param userIds
	 * @param roleIds
	 * @return
	 */
	@PostMapping("/grant")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "权限设置", notes = "传入roleId集合以及menuId集合")
	public R grant(@ApiParam(value = "userId集合", required = true) @RequestParam String userIds,
				   @ApiParam(value = "roleId集合", required = true) @RequestParam String roleIds) {
		boolean temp = userService.grant(userIds, roleIds);
		return R.status(temp);
	}

	@PostMapping("/reset-password")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "初始化密码", notes = "传入userId集合")
	public R resetPassword(@ApiParam(value = "userId集合", required = true) @RequestParam String userIds) {
		boolean temp = userService.resetPassword(userIds);
		return R.status(temp);
	}

	/**
	 * 修改密码
	 *
	 * @param oldPassword
	 * @param newPassword
	 * @param newPassword1
	 * @return
	 */
	@PostMapping("/update-password")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "修改密码", notes = "传入密码")
	public R updatePassword(SysUser user, @ApiParam(value = "旧密码", required = true) @RequestParam String oldPassword,
							@ApiParam(value = "新密码", required = true) @RequestParam String newPassword,
							@ApiParam(value = "新密码", required = true) @RequestParam String newPassword1) {
		boolean temp = userService.updatePassword(user.getUserId(), oldPassword, newPassword, newPassword1);
		return R.status(temp);
	}

	/**
	 * 用户列表
	 *
	 * @param user
	 * @return
	 */
	@GetMapping("/user-list")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "用户列表", notes = "传入user")
	public R<List<User>> userList(User user) {
		List<User> list = userService.list(Condition.getQueryWrapper(user));
		return R.data(list);
	}


	/**
	 * 导入用户
	 */
	@PostMapping("import-user")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "导入用户", notes = "传入excel")
	public R importUser(MultipartFile file, Integer isCovered) {
		String filename = file.getOriginalFilename();
		if (StringUtils.isEmpty(filename)) {
			throw new RuntimeException("请上传文件!");
		}
		if ((!StringUtils.endsWithIgnoreCase(filename, ".xls") && !StringUtils.endsWithIgnoreCase(filename, ".xlsx"))) {
			throw new RuntimeException("请上传正确的excel文件!");
		}
		InputStream inputStream;
		try {
			UserImportListener importListener = new UserImportListener(userService);
			inputStream = new BufferedInputStream(file.getInputStream());
			ExcelReaderBuilder builder = EasyExcel.read(inputStream, UserExcel.class, importListener);
			builder.doReadAll();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return R.success("操作成功");
	}

	/**
	 * 导出用户
	 */
	@SneakyThrows
	@GetMapping("export-user")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "导出用户", notes = "传入user")
	public void exportUser(@ApiIgnore @RequestParam Map<String, Object> user, SysUser sysUser, HttpServletResponse response) {
		QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
		if (!SecureUtil.isAdministrator()) {
			queryWrapper.lambda().eq(User::getTenantId, sysUser.getTenantId());
		}
		queryWrapper.lambda().eq(User::getIsDeleted, SysConstant.NOT_DELETED);
		List<UserExcel> list = userService.exportUser(queryWrapper);
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding(Charsets.UTF_8.name());
		String fileName = URLEncoder.encode("用户数据导出", Charsets.UTF_8.name());
		response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
		EasyExcel.write(response.getOutputStream(), UserExcel.class).sheet("用户数据表").doWrite(list);
	}

	/**
	 * 导出模板
	 */
	@SneakyThrows
	@GetMapping("export-template")
	@ApiOperationSupport(order = 14)
	@ApiOperation(value = "导出模板")
	public void exportUser(HttpServletResponse response) {
		List<UserExcel> list = new ArrayList<>();
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding(Charsets.UTF_8.name());
		String fileName = URLEncoder.encode("用户数据模板", Charsets.UTF_8.name());
		response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
		EasyExcel.write(response.getOutputStream(), UserExcel.class).sheet("用户数据表").doWrite(list);
	}

	/**
	 * 第三方注册用户
	 */
	@PostMapping("/register-guest")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "第三方注册用户", notes = "传入user")
	public R registerGuest(User user, Long oauthId) {
		return R.status(userService.registerGuest(user, oauthId));
	}

	@GetMapping("/listAll")
	@ApiOperationSupport(order = 16)
	@ApiOperation(value = "查询所有用户")
	public R<List<UserVO>> listAll(@ApiIgnore @RequestParam Map<String, Object> user, Query query, SysUser sysUser) {
		QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
		List<User> userList = userService.list(queryWrapper);
		return R.data(UserWrapper.build().listVO(userList));
	}

	@GetMapping("listUserAndDept")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "查询所有用户和部门")
	public R<Map<String, Object>> listUserAndDept(@ApiIgnore @RequestParam Map<String, Object> user, Query query, SysUser sysUser) {
		Map<String, Object> map = new HashMap<>();

		QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
		List<User> userList = userService.list(queryWrapper);

//		Map<String, Object> deptMap = new HashMap<>();
//		deptMap.put("id", user.get("deptId"));
//		QueryWrapper<Dept> deptQueryWrapper = Condition.getQueryWrapper(deptMap, Dept.class);
		List<DeptVO> deptList = deptService.lazyTree(Func.toStr(null, sysUser.getTenantId()), Long.valueOf(user.get("deptId").toString()));

		map.put("userList", UserWrapper.build().listVO(userList));
		map.put("deptList", deptList);

		return R.data(map);
	}

	private IRoleService roleService;

	@PostMapping("/listByRole")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "根据当前用户查询上级用户")
	@ApiImplicitParam(name = "roleType", value = "角色类型：0:当前登录用户的角色下的所有用户；1：一级角色用户；2：二级角色用户", paramType = "query", dataType = "int", required = true)
	public R<List<UserVO>> listByRole(@RequestParam Integer roleType,  SysUser sysUser) {
		User user = new User();
		List<Long> pRole = roleService.getRoleByIds(sysUser.getRoleId());
		List<User> userList = new ArrayList<>();
		if (pRole.isEmpty()) {
			return R.data(null);
		}
		if(roleType == 0){
			userList =userService.getUserByRoleIds(sysUser.getRoleId());
		}
		if (roleType == 1) {
			userList = userService.getUserByRoleIds(Func.join(pRole, ","));
			//user.setRoleId(Func.join(pRole,","));
		} else if (roleType == 2) {
			List<Long> pRole1 = roleService.getRoleByIds(Func.join(pRole, ","));
			if (ObjectUtil.isNotEmpty(pRole1)) {
				userList = userService.getUserByRoleIds(Func.join(pRole1, ","));
			}
		}
		return R.data(UserWrapper.build().listVO(userList));
	}

	@PostMapping("/listByRoleIds")
	@ApiOperationSupport(order = 19)
	@ApiOperation(value = "根据角色ids查询上级用户")
	@ApiImplicitParam(name = "roleIds", value = "角色ids(多个角色id用英文逗号隔开)", paramType = "query", dataType = "String", required = true)
	public R<List<UserVO>> listByRoleIds(@RequestParam String roleIds) {
		if (!StringUtils.hasText(roleIds)){
			List<UserVO> list = new ArrayList<>();
			return R.data(list);
		}
		List<Long> pRole = roleService.getRoleByIds(roleIds);
	    List<User>userList =userService.getUserByRoleIds(Func.join(pRole, ","));
		return R.data(UserWrapper.build().listVO(userList));
	}

	/**
	 * 根据角色名称查询该角色下的所有用户
	 * @param roleName
	 * @param sysUser
	 * @return
	 */
	@PostMapping("/listByRoleName")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "根据角色名称查询用户")
	@ApiImplicitParam(name = "roleName", value = "角色名称", paramType = "query", dataType = "String", required = true)
	public R<List<UserVO>> listByRoleName(@RequestParam String roleName,   SysUser sysUser) {
		User user = new User();
		Role role = new Role();
		role.setRoleName(roleName);
		Wrapper<Role> queryWrapper = new QueryWrapper<>(role);
		role = roleService.getOne(queryWrapper);
		List<User> userList = new ArrayList<>();
		if(role != null){
			userList = userService.getUserByRoleIds(String.valueOf(role.getId()));
		}
		return R.data(UserWrapper.build().listVO(userList));
	}

	/**根据当前用户查询所有上级用户信息（建议当用户数量在5万以上用此接口）暂时不用
	* @return: R<UserSuperVo>
	* @author wuning
	* @date: 2022/9/1 10:35
	*/
	@PostMapping("/selectUserSuperList")
	@ApiOperationSupport(order = 21)
	@ApiOperation(value = "根据当前用户查询所有上级用户信息（建议当用户数量在5万以上用此接口）暂时不用")
	public R<UserSuperVo> selectUserSuperList() {
		UserSuperVo userSuperVo = userService.selectUserSuperList(SecureUtil.getUserId());
		return R.data(userSuperVo);
	}

	/**查询用户表获取用户相对应所有上级用户信息（建议当用户数量在5万以下用此接口）
	 * @return: R<UserSuperVo>
	 * @author wuning
	 * @date: 2022/9/1 10:36
	 */
	@PostMapping("/selectAllUserSuperList")
	@ApiOperationSupport(order = 22)
	@ApiOperation(value = "查询用户表获取用户相对应所有上级用户信息（建议当用户数量在5万以下用此接口）")
	@ApiImplicitParam(name = "tier", value = "层级数，默认为3层", paramType = "query", dataType = "Integer")
	public R<UserSuperVo> selectAllUserSuperList(Integer tier) {
		if (tier == null || tier == 0) {
			tier = 3;
		}
		UserSuperVo userSuperVo = userService.selectAllUserSuperList(SecureUtil.getUserId(),tier);
		return R.data(userSuperVo);
	}
	/**修改库中所有表的字符集utf8mb4 字段为 utf8mb4_0900_ai_ci
	 * @author wuning
	 * @date: 2022/9/1 10:36
	 */
	@PostMapping("/updateTableNameUtf8mb4")
	@ApiOperationSupport(order = 23)
	@ApiOperation(value = "修改库中所有表的字符集utf8mb4 字段为 utf8mb4_0900_ai_ci")
	public R<?> updateTableNameUtf8mb4() throws InterruptedException {
		List<String> tableNameList = userService.selectTableNameList();
		if (tableNameList != null && tableNameList.size() > 0) {
			for (String tableName : tableNameList) {
				userService.updateTableNameUtf8mb4(tableName);
				Thread.sleep(1000);
			}
		}
		return R.data(null);
	}

	/**
	 * 校验用户角色，同时拥有外部与内部角色返回true，反之只拥护一种返回false，
	 * 因账号不能同时拥有外部与内部角色，并且当账号角色选择外部角色时为单选，所以需要判断
	 *
	 */
	private boolean verifyRole(User user) {
		if (StringUtils.hasLength(user.getRoleId())) {
			String roleId = user.getRoleId();
			Integer rolePro = user.getRoleProperty();
			//当账号角色选择外部角色时为单选
			if (rolePro != null && 1 == rolePro) {
				Long[] longs = Func.toLongArray(roleId);
				if (longs.length > 1) {
					return true;
				}
			}
			List<Role> roleInfoList = roleService.getRoleInfoByIds(Func.toLongArray(roleId));
			if (roleInfoList != null && roleInfoList.size() > 0) {
				int roleProperty = roleInfoList.get(0).getRoleProperty();
				boolean b = roleInfoList.stream().allMatch(a -> a.getRoleProperty() == roleProperty);
				if(!b){
					return true;
				}
				user.setRoleProperty(roleProperty);
			}
		}
		return false;
	}

//	@GetMapping("getUsersWithoutCurrent")
//	@ApiOperationSupport(order = 18)
//	@ApiOperation(value = "查询所有用户(排除当前用户)")
//	public R<List<UserVO>> getUsersWithoutCurrent(@ApiIgnore @RequestParam Map<String, Object> user, Query query, SysUser sysUser) {
//		QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
////		User currentUser = userService.getById(SecureUtil.getUser().getUserId());
//		queryWrapper.ne("id", SecureUtil.getUser().getUserId());
//		List<User> userList = userService.list(queryWrapper);
//		List<UserVO> userV0List = UserWrapper.build().listVO(userList);
//		// 用户的在线状态
//		userV0List = dealUserState(userV0List);
////		// 删除集合中当前元素
////		IntStream.range(0, userV0List.size()).filter(i -> userV0List.get(i).getId().compareTo( currentUser.getId())==0 )
////			.boxed().findFirst().map(i -> userV0List.remove((int)i));
//
//
//
//		return R.data(userV0List);
//	}

	/**
	 * 使用流对象的方法插入数据（用户的在线状态）
	 */
//	private List<UserVO> dealUserState(List<UserVO> userV0List) {
//
//		// 用户在线状态
//		List<UserState> userStateList = userStateService.list();
//
//		userV0List = userV0List.stream().map(userV0 -> {
//			return userStateList.stream().filter(state -> {        //条件判断
//				return userV0.getId().equals(state.getUserId());
//			}).map(state -> {
//				userV0.setUserState(state.getUserState());
//				return userV0;                            //返回的结果
//			}).collect(Collectors.toList());
//		}).flatMap(List::stream).collect(Collectors.toList());//设置返回结果类型
//
//		return userV0List;
//	}

	/**
	 * 当前用户所属的群消息
	 */
//	@GetMapping("/listDeptUser")
//	@ApiOperationSupport(order = 18)
//	@ApiOperation(value = "当前用户所属的群消息")
//	public List<DeptUserVO> selectDeptUserList() {
//
//		// 当前用户
//		SysUser user = SecureUtil.getUser();
//		// 当前用户所属部门
//		String[] deptIdList = user.getDeptId().split(",");
//
//		List<DeptUserVO> list = new ArrayList<DeptUserVO>();
//		QueryWrapper qw = new QueryWrapper();
//		for (int i = 0; i < deptIdList.length; i++) {
//			DeptUserVO info = new DeptUserVO();
//			qw.like("dept_id", deptIdList[i]);
//			List<User> userList = userService.list(qw);
//			List<UserVO> userV0List = UserWrapper.build().listVO(userList);
//			// 用户的在线状态
//			userV0List = dealUserState(userV0List);
//
//			Dept dept = deptService.getById(deptIdList[i]);
//			info.setDeptId(Long.valueOf(deptIdList[i]));
//			info.setDeptName(dept.getDeptName());
//			info.setUserInfo(userV0List);
//			list.add(info);
//		}
//		return list;
//	}

}
